﻿using Shop.Collect;
using Shop.ExtendService;
using Shop.Model;
using Shop.Model.DB;
using Shop.Model.FrontCategory;
using Shop.Model.FrontCategoryBind;
using Shop.RemoteModel.FrontCategory.Model;
using Shop.Service.Helper;
using Shop.Service.Interface;
using WeDonekRpc.Helper;

namespace Shop.Service.lmpl
{
    internal class FrontCategoryService : IFrontCategoryService
    {
        private readonly IFrontCategoryCollect _Service;
        private readonly ICategoryCollect _Category;
        private readonly IFrontCategoryBindCollect _CategoryBind;
        private readonly IFileService _File;
        public FrontCategoryService (IFrontCategoryCollect service,
            ICategoryCollect category,
            IFileService file,
            IFrontCategoryBindCollect categoryBind)
        {
            this._File = file;
            this._CategoryBind = categoryBind;
            this._Category = category;
            this._Service = service;
        }

        public long Add (FrontCategoryAdd add)
        {
            long id = this._Service.Add(add);
            if (add.FileId.HasValue)
            {
                this._File.Save(add.FileId.Value, id);
            }
            return id;
        }
        public bool Set (long id, FrontCategorySet set)
        {
            DBFrontCategory category = this._Service.Get(id);
            string icon = category.Icon;
            if (this._Service.Set(category, set))
            {
                this._File.Sync(set.FileId, id, icon);
                return true;
            }
            return false;
        }
        public void Delete (long id)
        {
            DBFrontCategory category = this._Service.Get(id);
            if (category.IsEnable)
            {
                throw new ErrorException("shop.front.category.already.enable");
            }
            long[] subId = this._Service.GetSubId(category);
            this._Service.Delete(category, subId);
            this._File.Drop(ShopFileDirDic.FrontCategoryIcon, subId.Add(id));
        }

        public void Disable (long id)
        {
            DBFrontCategory category = this._Service.Get(id);
            if (category.IsEnable)
            {
                this._Service.Stop(category);
            }
        }

        public void Enable (long id)
        {
            DBFrontCategory category = this._Service.Get(id);
            if (!category.IsEnable)
            {
                this._Service.Enable(category);
            }
        }

        public FrontCategoryDatum Get (long id)
        {
            return this._Service.Get<FrontCategoryDatum>(id);
        }

        public FrontCategoryFullTree[] GetFullTree ()
        {
            FrontCategoryData[] dtos = this._Service.GetAll();
            if (dtos.IsNull())
            {
                return Array.Empty<FrontCategoryFullTree>();
            }
            CategoryBindDto[] category = this._CategoryBind.GetAll();
            Dictionary<long, string> names = this._Category.GetNames(category.Distinct(a => a.CategoryId));
            return dtos.GetTree(category.GroupBy(a => a.FrontCategoryId).ToDictionary(a => a.Key, a => a.Select(c => new BindCategory
            {
                Id = c.CategoryId,
                Name = names[c.CategoryId]
            }).ToArray()));
        }

        public FrontCategoryTree[] GetTree (FrontCategoryGetParam param)
        {
            FrontCategoryGet dto = new FrontCategoryGet
            {
                IsEnable = param.IsEnable,
            };
            if (param.ParentId.HasValue)
            {
                dto.LevelCode = this._Service.Get(param.ParentId.Value, a => a.LevelCode) + param.ParentId.Value + "|";
            }
            FrontCategoryDto[] dtos = this._Service.Gets<FrontCategoryDto>(dto);
            return dtos.GetTree();
        }

        public void Move (long id, long? toId)
        {
            DBFrontCategory category = this._Service.Get(id);
            DBFrontCategory to = null;
            if (toId.HasValue)
            {
                to = this._Service.Get(toId.Value);
            }
            this._Service.Move(category, to);
        }

        public Dictionary<long, int> SetSort (long id, int sort)
        {
            DBFrontCategory category = this._Service.Get(id);
            return this._Service.SetSort(category, sort);
        }
    }
}
